package net.wanglu.www.zzz.rule.poss;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import net.wanglu.www.zzz.rule.BadEgg;
import net.wanglu.www.zzz.rule.Rule;

import org.apache.commons.lang3.StringUtils;

import edu.stanford.nlp.dcoref.CorefChain;
import edu.stanford.nlp.dcoref.CorefChain.CorefMention;
import edu.stanford.nlp.dcoref.Dictionaries;
import edu.stanford.nlp.trees.EnglishGrammaticalRelations;
import edu.stanford.nlp.trees.GrammaticalRelation;
import edu.stanford.nlp.trees.TreeGraphNode;
import edu.stanford.nlp.trees.TypedDependency;

public class ApostropheSPossessive extends _PossessiveRule {

	Pattern Exception = Pattern
			.compile("hair|heart|friendship|stone|finger|arm|wits");

	@Override
	public Object applicable(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		if (super.applicable(objects) == Rule.Inapplicable)
			return Rule.Inapplicable;

		HashMap<?, ?> preprocessData = (HashMap<?, ?>) objects[0];

		List<?> tdl = (List<?>) preprocessData.get("tdl");

		for (Object obj : tdl) {
			TypedDependency TD = (TypedDependency) obj;
			GrammaticalRelation reln = TD.reln();
			if (reln.equals(EnglishGrammaticalRelations.POSSESSIVE_MODIFIER)) {
				return Rule.Applicable;
			}

		}
		return Rule.Inapplicable;
	}

	@Override
	public Object deviseRightSolution(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object examine(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		if (this.applicable(objects) == Rule.Inapplicable)
			return Rule.Inapplicable;

		HashMap<?, ?> preprocessData = (HashMap<?, ?>) objects[0];

		List<?> tdl = (List<?>) preprocessData.get("tdl");
		Map<?, ?> coreChains = (Map<?, ?>) preprocessData.get("coreChains");

		Set<TreeGraphNode> possessives = new HashSet<TreeGraphNode>(16);
		for (Object obj : tdl) {
			TypedDependency TD = (TypedDependency) obj;
			GrammaticalRelation reln = TD.reln();
			if (reln.equals(EnglishGrammaticalRelations.POSSESSIVE_MODIFIER)) {
				possessives.add(TD.gov());
			}

		}

		Set<CorefMention> possessiveMentions = new HashSet<CorefMention>(16);
		for (Map.Entry<?, ?> entry : coreChains.entrySet()) {
			CorefChain cc = (CorefChain) entry.getValue();
			List<CorefMention> cml = cc.getMentionsInTextualOrder();
			for (CorefMention cm : cml) {
				if (StringUtils.endsWith(cm.mentionSpan, "'s")
						&& (cm.mentionType == Dictionaries.MentionType.PROPER)) {
					possessiveMentions.add(cm);
				}
			}
		}

		ArrayList<BadEgg> eggList = new ArrayList<BadEgg>(16);
		for (CorefMention cm : possessiveMentions) {
			if (cm.animacy == Dictionaries.Animacy.ANIMATE) {
				continue;
			} else if (Rule.Time.matcher(cm.mentionSpan).find()) {
				continue;
			} else if (Rule.Distance.matcher(cm.mentionSpan).find()) {
				continue;
			} else if (Rule.Planet.matcher(cm.mentionSpan).find()) {
				continue;
			} else if (Rule.Country.matcher(cm.mentionSpan).find()) {
				continue;
			} else if (Rule.City.matcher(cm.mentionSpan).find()) {
				continue;
			} else if (Rule.Company.matcher(cm.mentionSpan).find()) {
				continue;
			} else if (Rule.GroupOrg.matcher(cm.mentionSpan).find()) {
				continue;
			} else if (Rule.Univercity.matcher(cm.mentionSpan).find()) {
				continue;
			} else if (Rule.Continent.matcher(cm.mentionSpan).find()) {
				continue;
			} else if (Rule.Ocean.matcher(cm.mentionSpan).find()) {
				continue;
			} else if (this.Exception.matcher(cm.mentionSpan).find()) {
				continue;
			} else {
				BadEgg egg = new BadEgg();
				egg.setViolatedRule(this);
				egg.whereIsWrong = cm;
				eggList.add(egg);
			}
		}

		if (eggList.size() > 0)
			return eggList;
		return null;
	}

	@Override
	public Object whyItsWrong(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		sb.clear();
		sb.append("<p>");
		sb.append("表示有生命的东西的名词及某些表示时间、距离、星球、世界、国家、城市、地域、团体、机构等无生命的东西的名词后加 's来表示所有关系。");
		sb.append("<br>");
		sb.append("在某些习惯用语中，尽管是表示无生命的名词，也需要’s的所有格。例如：");
		sb.append("<br>");
		sb.append("The driver escaped the death by a hair's breadth.");
		sb.append("<br>");
		sb.append("Now you may sing to your heart’s content.");
		sb.append("<br>");
		sb.append("for friendship's sake, at a stone's throw, at one's finger's tip, at arm's length, at one's wits'end等。");
		sb.append("</p>");
		sb.append("<p>");
		sb.append("凡不能加's的名词，都可以与of构成短语，来表示所有关系。");
		sb.append("</p>");
		return sb.toString();
	}
}
